package jp.ddo.trismegistos.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.ddo.trismegistos.dao.DaoManager;
import jp.ddo.trismegistos.exception.RsException;

/**
 * @author Nagai Satoshi
 */
public class SqlExecutor extends AbstractBaseDao {

	public SqlExecutor(DaoManager manager) {
		super(manager);
	}

	protected <T> List<T> executeSelect(final String sql,
			final Map<Integer, Object> params, final Class<T> resultClass) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<T> result = null;
		try {
			conn = getConnection(false);
			ps = getPreparedStatement(conn, sql, params);
			rs = ps.executeQuery();
			result = processResult(rs, resultClass);
			conn.commit();
		} catch (final SQLException e) {
			rollBackConnection(conn);
		} catch (final RsException e) {
			rollBackConnection(conn);
		} finally {
			closeResultSet(rs);
			closeStatement(ps);
			closeConnection(conn);
		}
		return result;
	}

	public int executeInsert(final String sql, final Map<Integer, Object> params) {
		return executeUpdate(sql, params);
	}

	public int executeUpdate(final String sql, final Map<Integer, Object> params) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		int result = 0;
		try {
			conn = getConnection(false);
			ps = getPreparedStatement(conn, sql, params);
			result = ps.executeUpdate();
			conn.commit();
		} catch (final SQLException e) {
			rollBackConnection(conn);
		} finally {
			closeResultSet(rs);
			closeStatement(ps);
			closeConnection(conn);
		}
		return result;
	}

	public int executeDelete(final String sql, final Map<Integer, Object> params) {
		return executeUpdate(sql, params);
	}

	public boolean execute(final String sql, final Map<Integer, Object> params) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		boolean result = false;
		try {
			conn = getConnection(false);
			ps = getPreparedStatement(conn, sql, params);
			result = ps.execute();
			conn.commit();
		} catch (final SQLException e) {
			rollBackConnection(conn);
		} finally {
			closeResultSet(rs);
			closeStatement(ps);
			closeConnection(conn);
		}
		return result;
	}

	public boolean execute(final String sql) {
		return execute(sql, new HashMap<Integer, Object>());
	}

	private PreparedStatement getPreparedStatement(final Connection conn,
			final String sql, final Map<Integer, Object> params)
			throws SQLException {
		final PreparedStatement ps = conn.prepareStatement(sql);
		setParams(ps, params);
		return ps;
	}

	private void setParams(final PreparedStatement ps,
			final Map<Integer, Object> params) throws SQLException {
		for (final Map.Entry<Integer, Object> entry : params.entrySet()) {
			setValue(ps, entry.getKey(), entry.getValue());
		}
	}
}
